
#include "filesystem_monitor.h"
#include "utils.h"
#include "view.h"

#include "builders/bjam.h"
#include "builders/custom.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define BB_HANDLER_DEFINE(name) \
        static void bb_##name##_handler(void* arg0, struct bb_filesystem_change const* change) { \
            struct bb_##name##_builder* bdr = (struct bb_##name##_builder*)arg0; \
            bb_##name##_builder_on_filesystem_change(bdr, change); \
        }

BB_HANDLER_DEFINE(bjam) // bb_bjam_handler
BB_HANDLER_DEFINE(custom) // bb_custom_handler

static void init_filesystem_monitor_for_bjam(
        struct bb_filesystem_monitor*, struct bb_view*, int argc, char** argv);
static void init_filesystem_monitor_for_custom(
        struct bb_filesystem_monitor*, struct bb_view*, int argc, char** argv);
static void print_args_and_exit();

int main(int argc, char** argv)
{
    // Arguments
    if (argc < 2)
        print_args_and_exit();
    char const* const type = argv[1];

    // View
    struct bb_view view;
    bb_view_init(&view, &bb_view_stdout_output_listener, NULL);

    // Filesystem Monitor
    struct bb_filesystem_monitor fs_monitor;
    int directory_idx = 0;
    if (0 == strcmp("bjam", type)) {
        init_filesystem_monitor_for_bjam(&fs_monitor, &view, argc, argv);
        directory_idx = 2;
    } else if (0 == strcmp("custom", type)) {
        init_filesystem_monitor_for_custom(&fs_monitor, &view, argc, argv);
        directory_idx = 5;
    }
    else
        print_args_and_exit();

    // Add specified directories to monitor
    for (int idx = directory_idx; idx != argc; ++idx)
        bb_filesystem_monitor_add_directory(&fs_monitor, argv[idx]);

    // Run (TODO: until signal is caught, then graceful shutdown)
    bb_filesystem_monitor_run(&fs_monitor);

    return 0;
}

static void init_filesystem_monitor_for_bjam(
        struct bb_filesystem_monitor* fm, struct bb_view* view, int argc, char** argv)
{
    (void)argc; (void)argv;

    static struct bb_bjam_builder bdr;
    bb_bjam_builder_init(&bdr, view);
    bb_filesystem_monitor_init(fm, bb_bjam_handler, &bdr, view);
}

static void init_filesystem_monitor_for_custom(
        struct bb_filesystem_monitor* fm, struct bb_view* view, int argc, char** argv)
{
    // args
    if (argc < 6)
        print_args_and_exit();
    char const* all_cmd = argv[2];
    char const* clean_cmd = argv[3];
    char const* incremental_cmd = argv[4];
    
    static struct bb_custom_builder bdr;
    bb_custom_builder_init(&bdr, view, all_cmd, clean_cmd, incremental_cmd);
    bb_filesystem_monitor_init(fm, bb_custom_handler, &bdr, view);
}

static void print_args_and_exit()
{
    fprintf(stderr, "USAGE:\n"
                    "\tbuildbuddy bjam <directory>...\n"
                    "\tbuildbuddy custom <all cmd> <clean cmd> <increment cmd> <directory>...\n");
    exit(1);
}

